package com.afc.struts.bustle.commons.http;

import java.net.URI;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.afc.struts.bustle.commons.Converter;
import com.afc.struts.bustle.commons.Mapper;
import com.afc.struts.bustle.commons.StringParser;
import com.afc.struts.bustle.commons.dao.Dao;

abstract public class RestDtoDaoProxy<KeyType, DtoType> implements Dao<KeyType, DtoType>
{
  abstract protected List<DtoType> retrieveAllFrom(String aResult);

  public RestDtoDaoProxy(String anHost, int aPort, String aServiceName, StringParser aParser, Converter<DtoType, StringEntity> aDtoToEntityConverter, Class<DtoType> aDtoClass, Mapper<DtoType, DtoType> aDtoMapper)
  {
    host = anHost;
    port = aPort;
    serviceName = aServiceName;
    parser = aParser;
    dtoToEntityConverter = aDtoToEntityConverter;
    dtoType = aDtoClass;
    dtoMapper = aDtoMapper;
  }

  @Override
  public void create(DtoType aDto)
  {
    try
    {
      URIBuilder uriBuilder = createURIBuilder().setPath(PATH + "/" + serviceName + "/" + "create");
      URI uri = uriBuilder.build();
      String urlCreateDevises = uri.toString();
      HttpClient httpclient = new DefaultHttpClient();
      httpclient.getParams().setParameter("http.protocol.content-charset", "UTF-8");
      HttpPost httppost = new HttpPost(urlCreateDevises);
      httppost.setEntity(dtoToEntityConverter.convert(aDto));

      HttpResponse response = httpclient.execute(httppost);
      String result = EntityUtils.toString(response.getEntity());
      updateIdFrom(aDto, result);
    }
    catch (Exception anException)
    {
      anException.printStackTrace();
    }
  }

  @Override
  public DtoType retrieve(KeyType aKey)
  {
    try
    {
      URIBuilder uriBuilder = createURIBuilder().setPath(PATH + "/" + serviceName + "/" + "retrieve");
      uriBuilder = uriBuilder.setParameter("key", aKey.toString());
      URI uri = uriBuilder.build();
      HttpClient httpClient = new DefaultHttpClient();
      httpClient.getParams().setParameter("http.protocol.content-charset", "UTF-8");
      HttpGet httpGet = new HttpGet(uri);
      HttpResponse httpResponse = httpClient.execute(httpGet);
      String result = EntityUtils.toString(httpResponse.getEntity());
      return retrieveFrom(result);
    }
    catch (Exception anException)
    {
      anException.printStackTrace();
    }
    return null;
  }

  @Override
  public List<DtoType> retrieveAll()
  {
    try
    {
      URIBuilder uriBuilder = createURIBuilder().setPath(PATH + "/" + serviceName + "/" + "retrieveAll");
      URI uri = uriBuilder.build();
      HttpClient httpClient = new DefaultHttpClient();
      httpClient.getParams().setParameter("http.protocol.content-charset", "UTF-8");
      HttpGet httpGet = new HttpGet(uri);
      HttpResponse httpResponse = httpClient.execute(httpGet);
      String result = EntityUtils.toString(httpResponse.getEntity());
      return retrieveAllFrom(result);
    }
    catch (Exception anException)
    {
      anException.printStackTrace();
    }
    return null;
  }

  @Override
  public void update(DtoType aDto)
  {
    try
    {
      URIBuilder builder = createURIBuilder().setPath(PATH + "/" + serviceName + "/" + "update");
      URI uri = builder.build();
      String urlUpdateDevises = uri.toString();
      HttpClient httpclient = new DefaultHttpClient();
      httpclient.getParams().setParameter("http.protocol.content-charset", "UTF-8");
      HttpPut httpput = new HttpPut(urlUpdateDevises);
      httpput.setEntity(dtoToEntityConverter.convert(aDto));
      HttpResponse response = httpclient.execute(httpput);
    }
    catch (Exception anException)
    {
      anException.printStackTrace();
    }
  }

  @Override
  public void delete(KeyType aKey)
  {
    try
    {
      URIBuilder builder = createURIBuilder().setPath(PATH + "/" + serviceName + "/" + "delete/" + aKey.toString());
      URI uri = builder.build();
      HttpClient httpclient = new DefaultHttpClient();
      httpclient.getParams().setParameter("http.protocol.content-charset", "UTF-8");
      HttpDelete httpdelete = new HttpDelete(uri.toString());
      HttpResponse response = httpclient.execute(httpdelete);
    }
    catch (Exception anException)
    {
      anException.printStackTrace();
    }
  }

  protected URIBuilder createURIBuilder()
  {
    URIBuilder uriBuilder = new URIBuilder();
    uriBuilder.setScheme(PROTOCOL).setHost(host).setPort(port);
    return uriBuilder;
  }

  protected void updateIdFrom(DtoType aDto, String aResult)
  {
    dtoMapper.map(parser.parse(dtoType, aResult), aDto);
  }

  protected DtoType retrieveFrom(String anHttpResult)
  {
    return parser.parse(dtoType, anHttpResult);
  }

  protected String host;
  protected int port;
  protected String serviceName;
  protected StringParser parser;
  protected Converter<DtoType, StringEntity> dtoToEntityConverter;
  protected Class<DtoType> dtoType;
  protected Mapper<DtoType, DtoType> dtoMapper;

  static public final String PROTOCOL = "http";
  static public final String APP_NAME = "bustle-soa-web";
  static public final String SERVICE_TYPE = "rest";
  static public final String PATH = "/" + APP_NAME + "/" + SERVICE_TYPE;
}
